package com.project.service.Impl;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.project.bean.MtOrderBean;
import com.project.bean.MtTicketBean;
import com.project.bean.OrderBean;
import com.project.bean.UserBean;
import com.project.mapper.IMtOrderMapper;
import com.project.mapper.IMtTicketMapper;
import com.project.mapper.IUserMapper;
import com.project.service.IUserService;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.*;

@Service
@Transactional
public class UserServiceImpl implements IUserService {
    //创建一个log对象，在创建log对象时，要将当前类的Class对象作为参数传入
    // LoggerFactory.getLogger()方法中。
    // 这样，就可以在当前类的任意方法中使用该log对象进行日志记录了
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
    @Autowired
    private IUserMapper userMapper;
    @Autowired
    private IMtTicketMapper mtTicketMapper;

    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    private IMtOrderMapper mtOrderMapper;

    @Autowired
    RedisTemplate redisTemplate;//redis

    @Override
    public UserBean login(String username, String password) {
        QueryWrapper<UserBean> qw = new QueryWrapper<>();
        qw.eq("u_userName", username);
        qw.eq("u_password", password);
        UserBean userBean = userMapper.selectOne(qw);
        return userBean;
    }

    RabbitTemplate.ConfirmCallback callback = (CorrelationData correlationData, boolean b, String s) -> {
        String orderId = correlationData.getId();
        Integer id = Integer.valueOf(orderId);
        try {
            Thread.sleep(500);//睡眠4秒，等待数据库更新数据
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
//        System.out.println(Integer.valueOf(orderId));
//        System.out.println(mtOrderBean);
        MtOrderBean mtOrderBean = mtOrderMapper.selectById(id);
        if (b) {
            System.out.println("投递成功");
            //投递成功
            mtOrderBean.setStatus("投递成功");
        } else {
            //投递失败
            mtOrderBean.setStatus("投递失败");
        }
        mtOrderMapper.updateById(mtOrderBean);
    };

    @Override
    public void purchase(String userName, Integer mtTicketId) {
        //将订单放入redis缓存，订单状态为"Order in production"表示订单正在生成中
        String mtTicId=String.valueOf(mtTicketId);
        redisTemplate.opsForHash().put(userName + "Orders", mtTicId, "Order in production");
        //// 创建一个有界线程池，核心线程数为 5，最大线程数为 10，该阻塞队列最多可以容纳 100 个元素
        ExecutorService executorService = new ThreadPoolExecutor(
                5,10,0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(100)
        );

        executorService.execute(() -> {
            try {
                //从redis中得到订单的状态
                String orderStatus = (String) redisTemplate.opsForHash().get(userName + "Orders", mtTicId);
                System.out.println(userName);
                System.out.println(mtTicId);
                System.out.println("从redis中那东西"+orderStatus);
                if (null != orderStatus && orderStatus.equals("Order in production")) {
                    //查询电影票信息
                    MtTicketBean mtTicketBean = mtTicketMapper.selectById(mtTicketId);
                    //将电影票和购买人持久化到 美团的订单数据库
                    MtOrderBean order = new MtOrderBean(userName, mtTicketBean.getTicketId(), mtTicketBean.getMovieName(),
                            mtTicketBean.getPrice());

                    mtOrderMapper.insert(order);

                    // 发送消息到 RabbitMQ
                    rabbitTemplate.setMandatory(true);//开启消息通知
                    //绑定回调函数
                    rabbitTemplate.setConfirmCallback(callback);
                    String id = String.valueOf(order.getOrderId());
                    //创建关联对象
                    CorrelationData correlationData = new CorrelationData(id);
                    //封装order订单信息
                    OrderBean orderBean = new OrderBean(userName, order.getMtTickerId(), order.getMovieName(), order.getPrice());
                    //发送到Mq
                    String json = JSON.toJSONString(orderBean);
                    rabbitTemplate.convertAndSend("directExchangeOrder", "rabbit.order", json, correlationData);
                    Thread.sleep(400);
                        //redis中的状态改为完成
                    redisTemplate.opsForHash().put(userName + "Orders", mtTicId, "Order in finish");
                }
            } catch (Exception e) {
                // 记录异常信息
                log.error("购买电影票时发生异常，用户名为 {}，电影票 ID 为 {}", userName, mtTicketId, e);
                // 将订单状态改为 "Order failed"
                redisTemplate.opsForHash().put(userName + "Orders", mtTicId, "Order failed");
                // 抛出运行时异常
                throw new RuntimeException(e);
            }
        });
    }
}
